package compareResult.datasetCompare;

import com.supermap.data.*;

import java.util.ArrayList;

/**
 * Created by hanyz on 2016/11/9.
 */
public class CompareUtilities {

	public static boolean compareDouble(double d1, double d2, double torlerance) {
		return Math.abs(d1 - d2) < torlerance;
	}

	public static boolean compareDatasetTolerance(Tolerance expTolerance, Tolerance actualTolerance) throws Exception {
		//数据集容限值比较的精度，默认去0.00001d，随便设置的，后面根据经验修改
		return compareDatasetTolerance(expTolerance, actualTolerance, 0.00001d);
	}

	public static boolean compareDatasetTolerance(Tolerance expTolerance, Tolerance actualTolerance, double torlerance) throws Exception {
		if (expTolerance == null || actualTolerance == null) {
			throw new Exception("expTolerance:" + expTolerance + " actualTolerance:" + actualTolerance);
		}
		if (expTolerance.isEmpty() && actualTolerance.isEmpty()) {
			return true;
		}
		if (!compareDouble(expTolerance.getDangle(), actualTolerance.getDangle(), torlerance)) {
			throw new Exception("expToleranceDangle:" + expTolerance.getDangle() + " actualToleranceDangle:" + actualTolerance.getDangle() + " torlerance:" + torlerance);
		}
		if (!compareDouble(expTolerance.getExtend(), actualTolerance.getExtend(), torlerance)) {
			throw new Exception("expToleranceExtend:" + expTolerance.getExtend() + " actualToleranceExtend:" + actualTolerance.getExtend() + " torlerance:" + torlerance);
		}
		if (!compareDouble(expTolerance.getGrain(), actualTolerance.getGrain(), torlerance)) {
			throw new Exception("expToleranceGrain:" + expTolerance.getGrain() + " actualToleranceGrain:" + actualTolerance.getGrain() + " torlerance:" + torlerance);
		}
		if (!compareDouble(expTolerance.getNodeSnap(), actualTolerance.getNodeSnap(), torlerance)) {
			throw new Exception("expToleranceNodeSnap:" + expTolerance.getNodeSnap() + " actualToleranceNodeSnap:" + actualTolerance.getNodeSnap() + " torlerance:" + torlerance);
		}
		if (!compareDouble(expTolerance.getSmallPolygon(), actualTolerance.getSmallPolygon(), torlerance)) {
			throw new Exception("expSmallPolygon:" + expTolerance.getSmallPolygon() + " actualToleranceSmallPolygon:" + actualTolerance.getSmallPolygon() + " torlerance:" + torlerance);
		}
		return true;
	}

	/**
	 * 比较数据集投影
	 * 备注：Dataset.getPrjCoordSys()方法，当该数据集的投影采用其所在数据源的投影时，该方法返回 null；如果想要查看此时数据集的投影信息，请调用Datasource.getPrjCoordSys() 方法
	 *
	 * @param expPrjCoordSys
	 * @param actualPrjCoordSys
	 * @return
	 * @throws Exception
	 */
	public static boolean comparePrjCoordSys(PrjCoordSys expPrjCoordSys, PrjCoordSys actualPrjCoordSys) throws Exception {
		if (expPrjCoordSys == null && actualPrjCoordSys == null)
			return true;
		if (expPrjCoordSys == null || actualPrjCoordSys == null) {
			throw new Exception("expPrjCoordSys:" + expPrjCoordSys + " actualPrjCoordSys:" + actualPrjCoordSys);
		}
		if (!expPrjCoordSys.toXML().equals(actualPrjCoordSys.toXML())) {
			throw new Exception("expPrjCoordSys:" + expPrjCoordSys.toXML() + "\n" +
					"actualPrjCoordSys:" + actualPrjCoordSys.toXML());
		}
		return true;
	}

	/**
	 * 获取非系统字段，默认认为sm开头的字段是系统字段
	 *
	 * @param recordset
	 * @return
	 */
	public static ArrayList<FieldInfo> getNSYField(Recordset recordset) {
		ArrayList<FieldInfo> fArrayList = new ArrayList<>();
		for (int i = 0; i < recordset.getFieldCount(); i++) {
			FieldInfo fieldInfo = recordset.getFieldInfos().get(i);
			if (!fieldInfo.isSystemField() && !fieldInfo.getName().toLowerCase().startsWith("sm")) {
				fArrayList.add(fieldInfo);
			}
		}
		return fArrayList;
	}

	/**
	 * 获取字段，ignoreFields不作为结果的一部分
	 *
	 * @param recordset
	 * @return
	 */
	public static ArrayList<FieldInfo> getFields(Recordset recordset) {
		ArrayList<FieldInfo> fArrayList = new ArrayList<>();
		for (int i = 0; i < recordset.getFieldCount(); i++) {
			fArrayList.add(recordset.getFieldInfos().get(i));
		}
		return fArrayList;
	}

	/**
	 * 比较属性表结构
	 *
	 * @param expFieldInfos
	 * @param actualFieldInfos
	 * @return
	 * @throws Exception
	 */
	public static boolean compareFieldInfos(ArrayList<FieldInfo> expFieldInfos, ArrayList<FieldInfo> actualFieldInfos) throws Exception {
		if (expFieldInfos == null && actualFieldInfos == null)
			return true;
		if (expFieldInfos.size() != actualFieldInfos.size()) {
			throw new Exception("expFieldInfos count:" + expFieldInfos.size() + "\n" +
					"expFieldInfos count:" + actualFieldInfos.size());
		}
		for (int i = 0; i < expFieldInfos.size(); i++) {
			if (!isFieldInfosContains(expFieldInfos, actualFieldInfos.get(i))) {
				throw new Exception("expFieldInfos containing:" + expFieldInfos.get(i).getName() + "," +
						"actualFieldInfos not containing");
			}
		}
		return true;
	}

	public static boolean isFieldInfosContains(ArrayList<FieldInfo> expFieldInfos, FieldInfo actualFieldInfo) {
		for (FieldInfo expFieldInfo : expFieldInfos) {
			if (compareFieldInfo(expFieldInfo, actualFieldInfo)) {
				return true;
			}
		}
		return false;
	}

	public static boolean compareFieldInfo(FieldInfo expFieldInfo, FieldInfo actualFieldInfo) {
		if (expFieldInfo.equals(actualFieldInfo)) {
			return true;
		}
		if (expFieldInfo.getName().equals(actualFieldInfo.getName()) &&
				expFieldInfo.getType().equals(actualFieldInfo.getType()) &&
				expFieldInfo.getCaption().equals(actualFieldInfo.getCaption()) &&
				expFieldInfo.getMaxLength() == actualFieldInfo.getMaxLength() &&
				expFieldInfo.getDefaultValue().equals(actualFieldInfo.getDefaultValue())) {
			return true;
		}
		return false;
	}

	/**
	 * 比较记录集：属性和geometry
	 *
	 * @param expRecordset
	 * @param actualRecordset
	 * @param tolerance
	 * @return
	 * @throws Exception
	 */
	public static boolean compareRecordset(Recordset expRecordset, Recordset actualRecordset, ArrayList<FieldInfo> fieldInfos, double tolerance) throws Exception {
		if (expRecordset == null || actualRecordset == null) {
			throw new Exception("expRecordset:" + expRecordset + " actualRecordset:" + actualRecordset);
		}
		if (expRecordset.getRecordCount() != actualRecordset.getRecordCount()) {
			throw new Exception("expRecordCount:" + expRecordset.getRecordCount() + " actualRecordCount:" + actualRecordset.getRecordCount());
		}
		if (fieldInfos == null) {
			return true;
		}
		expRecordset.moveFirst();
		actualRecordset.moveFirst();
		while (!expRecordset.isEOF()) {
			//调用组件方法比较记录属性值
			for (int i = 0; i < fieldInfos.size(); i++) {
				Object expObject = expRecordset.getFieldValue(fieldInfos.get(i).getName());
				Object actualObject = actualRecordset.getFieldValue(fieldInfos.get(i).getName());
				if (!EqualAssert.isValueEqual(expObject, actualObject, tolerance)) {
					throw new Exception("fieldValue:" + fieldInfos.get(i).getName() + " not equal:" + "" +
							"\nexpRecordset" + expRecordset.getID() + ":" + expObject +
							"\nactualRecordset" + actualRecordset.getID() + ":" + actualObject);
				}
			}
			//比较geometry
			Geometry expGeometry = expRecordset.getGeometry();
			Geometry actualGeometry = actualRecordset.getGeometry();
			if (expGeometry == null && actualGeometry == null) {
				return true;
			}
			if (expGeometry == null || actualGeometry == null) {
				throw new Exception("expGeometry" + expGeometry + "actualGeometry" + actualGeometry);
			}
			if (!EqualAssert.isGeometryEqual(expGeometry, actualGeometry)) {
				throw new Exception("geometry not equal:" + "expRecordset" + expRecordset.getID() + " actualRecordset" + actualRecordset.getID());
			}
			expRecordset.moveNext();
			actualRecordset.moveNext();
		}
		return true;
	}


}
